-
-
Notifications
You must be signed in to change notification settings - Fork 346
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Kinetics] Fix issue 717, Add check for sticking coefficient more than 1 #1038
Conversation
Codecov Report
@@ Coverage Diff @@
## main #1038 +/- ##
==========================================
+ Coverage 66.04% 73.53% +7.48%
==========================================
Files 313 365 +52
Lines 44908 48240 +3332
Branches 19114 0 -19114
==========================================
+ Hits 29658 35471 +5813
- Misses 12669 12769 +100
+ Partials 2581 0 -2581
Continue to review full report at Codecov.
|
While this looks pretty good, I believe that the validation should be implemented strictly within
For temperatures, it may make sense to just check the range where species thermo information of reactants and products is valid? |
@12Chao Have you been able to update this PR in response to the review? Thanks! |
21cfce9
to
832d196
Compare
Sorry for the late response, I agree that there could be a better place for validate functions, but I cannot figure out where is more reasonable for these functions given that an |
You can just evaluate the rate constant at the specified set of temperatures in |
Yes, |
I'm not sure there's that much reason to worry about future changes to use the new
I am not suggesting moving the validation to the void InterfaceReaction::validate() {
ElementaryReaction::validate();
if (is_sticking_coefficient) {
for (double T : temperatureList) {
k = rate.updateRC(log(T), 1.0/T);
if (k > 1) {
throw InputFileError("InterfaceReaction::validate", input, "bad sticking factor");
}
}
}
} I think you'll need to do something a little more complex to validate this for Blowers-Masel reactions, given your parameter space now has two dimensions. |
@speth Thanks for the instruction, Could you please give me a hint about how to call the |
A Doing that would complicate things a bit -- you'd probably need to pass the |
Thanks for all the help, I have addressed all the comments for this PR and would be appreciated if anyone could review the new changes |
@12Chao ... thanks for your work on this. But I do have a philosophical question - checking the sticking coefficient here goes in the direction of a mechanism check, which is historically not really done within Cantera but relegated to external tools (e.g. ChemCheck, see Cantera/enhancements#42). In another context, you'll see some warnings (e.g. thermo data with discontinuities), but that's about that. Throwing an error means that a (potentially inexperienced) user would have to fix the YAML file in order to proceed. If they just happened to convert a (buggy) CHEMKIN file from some web repository, this would mean that in most cases those users would be stuck and post on the user group, etc.. So the main question here (which goes beyond syntax) would be:
Regarding changing the signature of PS: Sorry if this goes beyond my original feedback (which was strictly on code/implementation); I meant to post some update since, but haven't gotten around that until now. |
@ischoegl Thanks for the comments. Moving the check to ChemCheck is not a hard task, and I can definately work on that in the future.
I'm not sure how to deal with the problematic sticking coefficient except raising an error message, but I think at least we need to warn the user if their sticking coefficient exceeds the limit.
I'm a little confused about this comment. The
This is a good point, I am currently just doing the same check like the PLOG reaction validation, but I can try to move the validate functions to |
It's a pretty subtle point. A lot of the My (admittedly personal) opinion here is to use arguments as frugally as possible (i.e. don't add them unless absolutely needed), which would favor the case against changing the current |
Thanks for the suggestion! I'll try to come up with a better way to avoid the changes to these |
Sure. But wait for others to weigh in also - whatever you do, these subtle points shouldn't keep you from wrapping this work up. Passing My main point is that you should be careful raising an error where other codes (chemkin?) may not find an issue. Having a converted buggy mechanism fail would create some unnecessary repercussions on the user group where simply limiting the output to 1 would be easier. Just looking at the code, having |
I agree in general, but I think that this isn't actually the only case where having the
The point where validation is called isn't changed here, is it? Generally, it will be called at the point when a reaction is added to the
I think it's possible to make a useful distinction between checking for issues in an input file and a tool for helping figure out what's actually wrong with the input file and how to fix it. I'd say the first part is something that is good to build directly into Cantera. Otherwise, people are going to just blithely use mechanisms with these problems and are not going to do the due diligence of running them through I do agree that automatically treating this as an error might be a bit extreme, and by analogy with how Cantera treats discontinuous thermo data, it might make sense to have the default behavior here be to just issue a warning. I'm sure we'll still get some posts to the Users' Group, though. |
and
👍 I agree ...
This is technically true for the YAML route, but only as things happen in a direct sequence. As you mentioned, this is not universally true: My main point is that I hope to avoid an across-the-board In other words, I am asking for //! @deprecated To be removed after Cantera 2.6
virtual void validate(); to be reconsidered. |
I can keep the validation function as is, if we all agree on throw a warning instead of an error. |
Another way to raise the warning for problematic sticking coefficient at the current temperature is to add
in |
OK, that makes sense to me. Being able to catch issues that don't need the @12Chao, can you update to reflect this consensus? I hope you still have a branch with the version where you added the |
I have updated the code, but I didn't figure out how to write a test to catch the |
@12Chao ... The way I've seen this done is to make Cantera warnings fatal ( Caveat: This is for deprecation errors and thus is not necessarily the easiest approach ... I guess I responded too fast. |
Yeah, I don't think we currently have a way of testing warnings issued by the C++ If you want to be able to test the warning message being generated here, I guess you could add a similar global flag like we use for deprecation warnings to temporarily make the warnings into errors and catch that exception -- see the implementation of This is related to Cantera/enhancements#112, where the feature described there would make it easier to make trap the warning in a Python test. One short-term option is to just have a test that issues this warning and leave testing whether that is actually the case as a "TODO" item, and we can accept that the fact that the test coverage will show this bit of code being called as good enough for now. |
Thanks! I have made a new function to convert |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the updates, @12Chao. I think we'll find being able to test warning messages handy in some other cases as well.
I have some suggested revisions that I think will help simplify the implementation of the new validation methods.
include/cantera/base/global.h
Outdated
@@ -215,6 +215,9 @@ void warn_user(const std::string& method, const std::string& msg, | |||
//! @copydoc Application::make_deprecation_warnings_fatal | |||
void make_deprecation_warnings_fatal(); | |||
|
|||
//! @copydoc Application::make_cantera_warnings_fatal | |||
void make_cantera_warnings_fatal(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this function can just be named make_warnings_fatal
. Likewise for the Python function.
virtual double rxn_enthalpy(const Composition& reactants, const Composition& products); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function needs a docstring. I'd also suggest reactionEnthalpy
as a name that's more consistent with other function names in Cantera's C++ code.
include/cantera/kinetics/Kinetics.h
Outdated
virtual double rxn_enthalpy(const Composition& reactants, const Composition& products){ | ||
return 0; | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understand that this function only gets used for InterfaceKinetics
, but is there a reason for it to be implemented only for that class? Would the implementation for Kinetics
be any different? Having it return 0 here seems not ideal.
include/cantera/kinetics/Reaction.h
Outdated
//! New validate function takes kinetics object as the input | ||
virtual void validate(Kinetics& kin); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the docstring, I'd suggest something along the lines of "Perform validation checks that need access to a complete Kinetics
objects, for example to retrieve information about reactant / product species. Also, the existing docstring for the validate()
method shouldn't be removed.
include/cantera/kinetics/Reaction.h
Outdated
//! New validate function takes kinetics object as the input | ||
virtual void validate(Kinetics& kin); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should only add a docstring to the base class's declaration, unless there is something different about this class's implementation that needs to be noted.
src/kinetics/Reaction.cpp
Outdated
doublereal original_T = kin.thermo().temperature(); | ||
doublereal original_P = kin.thermo().pressure(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please don't use doublereal
in any new code -- just write double
.
src/kinetics/RxnRates.cpp
Outdated
@@ -88,6 +90,7 @@ void Arrhenius::getParameters(AnyMap& rateNode, const Units& rate_units) const | |||
rateNode.setFlowStyle(); | |||
} | |||
|
|||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please revert changes that are just changing whitespace unrelated to your actual updates (ideally, by doing a fixup commit so that there isn't a commit adding this blank line and then another removing it).
src/kinetics/RxnRates.cpp
Outdated
#include "cantera/base/global.h" | ||
#include <math.h> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are these includes needed? especially the latter seems suspect in light of #1110.
try: | ||
ct.make_cantera_warnings_fatal() | ||
gas = ct.Solution('sticking_coeff_check.yaml') | ||
surface = ct.Interface('sticking_coeff_check.yaml', 'Pt_surf', [gas]) | ||
self.fail('CanteraError not raised') | ||
except ct.CanteraError as e: | ||
err_msg_list = str(e).splitlines() | ||
for msg in err_msg: | ||
self.assertIn(msg, err_msg_list) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Check some of the other code that uses the with self.assertRaises
construct for a nicer way of doing this.
include/cantera/kinetics/RxnRates.h
Outdated
@@ -212,6 +216,7 @@ class BlowersMasel | |||
return m_w; | |||
} | |||
|
|||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please avoid the extraneous whitespace changes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@12Chao ... thanks! As far as I can tell, you addressed most of @speth's comments. I also appreciate that you left the original validate
in place, and implemented the make_warnings_fatal
capability (which I believe will be useful). I noticed one instance where you may be able to leverage existing code as commented on below.
@@ -109,6 +109,6 @@ def change_species_enthalpy(gas, species_name, dH): | |||
plt.plot(deltaH_list, Ea_list) | |||
plt.xlabel("Enthalpy Change (J/kmol)") | |||
plt.ylabel("Activation Energy Change (J/kmol)") | |||
plt.title(r"$E_a$ vs. $\Delta H$ For O+H2<=>H+OH", y=1.1) | |||
plt.title(r"$E_a$ vs. $\Delta{H}$ For O+H2<=>H+OH", y=1.1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rather than undoing the edit, could you just drop the previous commit? (05ab001)
vector_fp hk(nTotalSpecies()); | ||
for (size_t n = 0; n < nPhases(); n++) { | ||
thermo(n).getPartialMolarEnthalpies(&hk[m_start[n]]); | ||
} | ||
double rxn_deltaH = 0; | ||
for (const auto& product : products) { | ||
size_t k = kineticsSpeciesIndex(product.first); | ||
double stoich = product.second; | ||
rxn_deltaH += hk[k] * stoich; | ||
} | ||
for (const auto& reactant : reactants) { | ||
size_t k = kineticsSpeciesIndex(reactant.first); | ||
double stoich = reactant.second; | ||
rxn_deltaH -= hk[k] * stoich; | ||
} | ||
return rxn_deltaH; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a way to use
cantera/include/cantera/kinetics/Kinetics.h
Lines 392 to 407 in 4570f3e
/** | |
* Change in species properties. Given an array of molar species property | |
* values \f$ z_k, k = 1, \dots, K \f$, return the array of reaction values | |
* \f[ | |
* \Delta Z_i = \sum_k \nu_{k,i} z_k, i = 1, \dots, I. | |
* \f] | |
* For example, if this method is called with the array of standard-state | |
* molar Gibbs free energies for the species, then the values returned in | |
* array \c deltaProperty would be the standard-state Gibbs free energies of | |
* reaction for each reaction. | |
* | |
* @param property Input vector of property value. Length: m_kk. | |
* @param deltaProperty Output vector of deltaRxn. Length: nReactions(). | |
*/ | |
virtual void getReactionDelta(const doublereal* property, | |
doublereal* deltaProperty); |
here? I have recently used
bulk.getPartialMolarEnthalpies(m_grt.data());
getReactionDelta(m_grt.data(), dH.data());
(this used just one phase, with dH
being a vector with the length of the number of reactions); I believe this may extend to multiple phases as long as the partial molar enthalpies are in the correct order. You mainly need to pick out the correct reaction index (while this calculates things for all reactions, it does not require lookup; it's a tradeoff, but as it is called during validation speed may not be as critical).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the review, I think I have addressed all the comments except this one. I would rather not change this part if it is not going to significantly speed things up
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@12Chao … no problem. I’ll leave the final approval to @speth. From my perspective, what you have here may be redundant code that could be avoided, as the same may be achieved with 5 lines of code within your validation functions. Another option would be to make this a local function within Reaction.cpp
, as it is not being used elsewhere and I do not think that it is a good fit for Kinetics
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought that the reason for adding the deltaEnthalpy
function was because you need to be able to evaluate it for a reaction that isn't already part of the Kinetics
object. Correct?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@speth … valid point: in this case getReactionDelta
does not apply. It still doesn’t quite fit with Kinetics
and I believe it would be better to have it as a helper function within Reaction
. But it’s not a major sticking point for me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree, it does feel like an awkward addition to the Kinetics class. Given that it relies almost entirely on public member functions of Kinetics
(and the one exception, the use of m_start
, can be fixed), I can see it more naturally being a member of the Reaction
class.
Changes proposed in this pull request
6 different temperature points from 200K to 10000K for
InterfaceReaction
andBlowersMaselInterfaceReaction
. Any temperature point with sticking coefficient more than 1 will be added into error message.If applicable, fill in the issue number this pull request is fixing
Closes #717
If applicable, provide an example illustrating new features this pull request is introducing
Checklist
scons build
&scons test
) and unit tests address code coverage